package ui;

import ui.controls.*;
import ui.control.binary.States;
import ui.control.button.ButtonColors;
import ui.control.button.ButtonSizes;
import ui.control.button.ButtonTypes;
import ui.control.led.*;
import ui.control.switches.*;

import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import cpu.components.*;

import javax.swing.JFrame;

class ExitListener extends WindowAdapter {
	public void windowClosing( WindowEvent event ) {
		System.exit(0);
	}
}

public class Console {
	
	public LEDBank ledbankBooting;
	public LEDBank ledbankStop;
	public LEDBank ledbankRun;

	public LEDBank ledbankCC0;
	public LEDBank ledbankCC1;
	public LEDBank ledbankCC2;
	public LEDBank ledbankCC3;

	public LEDBank ledbankR0;
	public LEDBank ledbankR1;
	public LEDBank ledbankR2;
	public LEDBank ledbankR3;

	public LEDBank ledbankPC;
	public LEDBank ledbankIR;
	
	public LEDBank ledbankX0;
	public LEDBank ledbankEA;

	public LEDBank ledbankMAR;
	public LEDBank ledbankMBR;

	public LEDBank ledbankMSR;
	public LEDBank ledbankMFR;

	public LEDBank ledbankCacheMAR;
	public LEDBank ledbankCacheMBR;

	public SwitchBank switchbank;
	public DialBank registerSelector;
	private int selectedRegister = 0;
	public DialBank latencySelector;
	
	public ButtonBank IPL;
	public ButtonBank StartStop;
	public ButtonBank Commit;
	public ButtonBank Step;
	
	public int sleep_interval = 10;
	
	public JFrame window;
	
	private int width, height;
	
	public CPU cpu;
	
	public Console( ) {
		ui.Assets assets = new Assets( );

	    ledbankBooting = new LEDBank( assets, "BOOT", 1, LEDColors.AMBER, LEDSizes._24 );
	    ledbankStop = new LEDBank( assets, "HALT", 1, LEDColors.RED, LEDSizes._24 );
	    ledbankRun = new LEDBank( assets, "RUN", 1, LEDColors.GREEN, LEDSizes._24 );

	    ledbankCC0 = new LEDBank( assets, "CC0", 1, LEDColors.BLUE, LEDSizes._16 );
	    ledbankCC1 = new LEDBank( assets, "CC1", 1, LEDColors.BLUE, LEDSizes._16 );
	    ledbankCC2 = new LEDBank( assets, "CC2", 1, LEDColors.BLUE, LEDSizes._16 );
	    ledbankCC3 = new LEDBank( assets, "CC3", 1, LEDColors.BLUE, LEDSizes._16 );

	    ledbankR0 = new LEDBank( assets, "R0", 16, LEDColors.RED, LEDSizes._16 );
	    ledbankR1 = new LEDBank( assets, "R1", 16, LEDColors.RED, LEDSizes._16 );
	    ledbankR2 = new LEDBank( assets, "R2", 16, LEDColors.RED, LEDSizes._16 );
	    ledbankR3 = new LEDBank( assets, "R3", 16, LEDColors.RED, LEDSizes._16 );

	    ledbankPC = new LEDBank( assets, "PC", 16, LEDColors.RED, LEDSizes._16 );
	    ledbankIR = new LEDBank( assets, "IR", 16, LEDColors.RED, LEDSizes._16 );

	    ledbankX0 = new LEDBank( assets, "X0", 16, LEDColors.RED, LEDSizes._16 );
	    ledbankEA = new LEDBank( assets, "EA", 16, LEDColors.RED, LEDSizes._16 );
	    
	    ledbankMAR = new LEDBank( assets, "MAR", 16, LEDColors.RED, LEDSizes._16 );
	    ledbankMBR = new LEDBank( assets, "MBR", 16, LEDColors.RED, LEDSizes._16 );

	    ledbankMSR = new LEDBank( assets, "MSR", 16, LEDColors.RED, LEDSizes._16 );
	    ledbankMFR = new LEDBank( assets, "MFR", 4, LEDColors.RED, LEDSizes._16 );

	    ledbankCacheMAR = new LEDBank( assets, "CMAR", 16, LEDColors.YELLOW, LEDSizes._16 );
	    ledbankCacheMBR = new LEDBank( assets, "CMBR", 16, LEDColors.YELLOW, LEDSizes._16 );

	    switchbank = new SwitchBank( assets, this, "", 16, SwitchColors.BLACK, SwitchSizes._16 );
	    
	    IPL = new ButtonBank( assets, this, "IPL", 1, ButtonColors.GREEN, ButtonSizes._24, ButtonTypes.SPRING );
	    StartStop = new ButtonBank( assets, this, "Start/Stop", 1, ButtonColors.RED, ButtonSizes._24, ButtonTypes.TOGGLE );
	    Commit = new ButtonBank( assets, this, "Commit", 1, ButtonColors.YELLOW, ButtonSizes._24, ButtonTypes.SPRING );
	    Step = new ButtonBank( assets, this, "Step", 1, ButtonColors.BLUE, ButtonSizes._24, ButtonTypes.SPRING );
	    
	    String[] diallabels = new String[8];
	    diallabels[0] = new String ( "R0" );
	    diallabels[1] = new String ( "R1" );
	    diallabels[2] = new String ( "R2" );
	    diallabels[3] = new String ( "R3" );
	    diallabels[4] = new String ( "IR" );
	    diallabels[5] = new String ( "PC" );
	    diallabels[6] = new String ( "MAR" );
	    diallabels[7] = new String ( "X0" );
	    registerSelector = new DialBank( assets, this, "Register Select", 1, ui.control.dial.DialSizes._64, diallabels );

	    String[] labelslatencyselector = new String[8];
	    labelslatencyselector[0] = new String ( "0" );
	    labelslatencyselector[1] = new String ( "1" );
	    labelslatencyselector[2] = new String ( "2" );
	    labelslatencyselector[3] = new String ( "5" );
	    labelslatencyselector[4] = new String ( "10" );
	    labelslatencyselector[5] = new String ( "20" );
	    labelslatencyselector[6] = new String ( "50" );
	    labelslatencyselector[7] = new String ( "100" );
	    latencySelector = new DialBank( assets, this, "Latency (ms)", 1, ui.control.dial.DialSizes._64, labelslatencyselector );

		width = ledbankR0.getWidth( ) * 3 + 64;
		height = 16 + ledbankR0.getHeight( ) * 8 + 64;

	    window = new JFrame("CS6461 Computer Console");
	}
	
	public int getWidth( ) {
		return width;
	}

	public int getHeight( ) {
		return height;
	}

	public void show( ) {
		int row1 = 16;
		int row2 = row1 + ledbankR0.getHeight( );
		int row3 = row1 + ledbankR0.getHeight( ) * 2;
		int row4 = row1 + ledbankR0.getHeight( ) * 3;
		int row5 = row1 + ledbankR0.getHeight( ) * 4;
		int row6 = row1 + ledbankR0.getHeight( ) * 5;
		int row7 = row1 + ledbankR0.getHeight( ) * 6;
		int row8 = row1 + ledbankR0.getHeight( ) * 7;
		int row9 = row1 + ledbankR0.getHeight( ) * 8;
		
		int col1 = 0;
		int col2 = ledbankR0.getWidth( );
		int col3 = ledbankR0.getWidth( ) * 2;

		window.setLayout( null );
		
		window.setSize( width, height );
		window.setLocation( 0, 0 );
		
	    Container content = window.getContentPane( );
	    
	    ledbankR0.setLocation( col1, row1 );
	    content.add( ledbankR0 );
	    ledbankR1.setLocation( col1, row2 );
	    content.add( ledbankR1 );
	    ledbankR2.setLocation( col1, row3 );
	    content.add( ledbankR2 );
	    ledbankR3.setLocation( col1, row4 );
	    content.add( ledbankR3 );
	    ledbankPC.setLocation( col1, row5 );
	    content.add( ledbankPC );
	    ledbankIR.setLocation( col1, row6 );
	    content.add( ledbankIR );

	    ledbankMAR.setLocation( col2, row1 );
	    content.add( ledbankMAR );
	    ledbankMBR.setLocation( col2, row2 );
	    content.add( ledbankMBR );
	    ledbankCacheMAR.setLocation( col2, row3 );
	    content.add( ledbankCacheMAR );
	    ledbankCacheMBR.setLocation( col2, row4 );
	    content.add( ledbankCacheMBR );
	    ledbankX0.setLocation( col2, row5 );
	    content.add( ledbankX0 );
	    ledbankEA.setLocation( col2, row6 );
	    content.add( ledbankEA );

	    int ccpos = col3;
	    ledbankCC0.setLocation( ccpos, row1 );
	    ccpos += ledbankCC0.getWidth(); 
	    content.add( ledbankCC0 );
	    ledbankCC1.setLocation( ccpos, row1 );
	    ccpos += ledbankCC1.getWidth();
	    content.add( ledbankCC1 );
	    ledbankCC2.setLocation( ccpos, row1 );
	    ccpos += ledbankCC2.getWidth();
	    content.add( ledbankCC2 );
	    ledbankCC3.setLocation( ccpos, row1 );
	    content.add( ledbankCC3 );
	    
	    ledbankMSR.setLocation( col3, row2 );
	    content.add( ledbankMSR );
	    ledbankMFR.setLocation( col3, row3 );
	    content.add( ledbankMFR );

	    int dialpos = col3 + 64;
	    registerSelector.setLocation( dialpos, row4 );
	    content.add( registerSelector );
	    dialpos += registerSelector.getWidth();

	    latencySelector.setLocation( dialpos, row4 );
	    content.add( latencySelector );

	    switchbank.setLocation( col3, row7 );
	    content.add( switchbank );

	    int bankpos = col1;
	    ledbankBooting.setLocation( bankpos, row8 );
	    bankpos += ledbankBooting.getWidth( );
	    content.add( ledbankBooting );

	    ledbankStop.setLocation( bankpos, row8 );
	    bankpos += ledbankStop.getWidth( );
	    content.add( ledbankStop );

	    ledbankRun.setLocation( bankpos, row8 );
	    bankpos += ledbankRun.getWidth( );
	    content.add( ledbankRun );

	    bankpos = col2;
	    IPL.setLocation( bankpos, row8 );
	    bankpos += IPL.getWidth( );
	    content.add( IPL );
	    
	    StartStop.setLocation( bankpos, row8 );
	    bankpos += StartStop.getWidth( );
	    content.add( StartStop );
	    
	    Step.setLocation( bankpos, row8 );
	    bankpos += Step.getWidth( );
	    content.add( Step );

	    Commit.setLocation( col3, row8 );
	    bankpos += Commit.getWidth( );
	    content.add( Commit );

	    window.addWindowListener( new ExitListener( ) );
	    window.setVisible( true );
	}
	
	public void changed( SwitchBank bank, int i, ui.control.binary.States state ) {
		if( bank.equals( switchbank ) ) {
			switch( selectedRegister ) {
			case 0:
				if( state == States.ON)
					ledbankR0.toggleOn( i );
				else 
					ledbankR0.toggleOff( i );
				break;
			case 1:
				if( state == States.ON)
					ledbankR1.toggleOn( i );
				else 
					ledbankR1.toggleOff( i );
				break;
			case 2:
				if( state == States.ON)
					ledbankR2.toggleOn( i );
				else 
					ledbankR2.toggleOff( i );
				break;
			case 3:
				if( state == States.ON)
					ledbankR3.toggleOn( i );
				else 
					ledbankR3.toggleOff( i );
				break;
			case 4:
				if( state == States.ON)
					ledbankIR.toggleOn( i );
				else 
					ledbankIR.toggleOff( i );
				break;
			case 5:
				if( state == States.ON)
					ledbankPC.toggleOn( i );
				else 
					ledbankPC.toggleOff( i );
				break;
			case 6:
				if( state == States.ON)
					ledbankMAR.toggleOn( i );
				else 
					ledbankMAR.toggleOff( i );
				break;
			case 7:
				if( state == States.ON)
					ledbankX0.toggleOn( i );
				else 
					ledbankX0.toggleOff( i );
				break;
			}
		}		
	}
	
	public void changed( ButtonBank bank, int i, ui.control.binary.States state ) {
		
	}
	
	public void changed( DialBank bank, int i, ui.control.dial.DialStates state ) {
		
		if( bank == registerSelector ) {
			switch( state ) {
			case UP:
				selectedRegister = 0;
				break;
			case UPRIGHT:
				selectedRegister = 1;
				break;
			case RIGHT:
				selectedRegister = 2;
				break;
			case DOWNRIGHT:
				selectedRegister = 3;
				break;
			case DOWN:
				selectedRegister = 4;
				break;
			case DOWNLEFT:
				selectedRegister = 5;
				break;
			case LEFT:
				selectedRegister = 6;
				break;
			case UPLEFT:
				selectedRegister = 7;
				break;
			}
		}
	}
}
